package com.greensam.pixelengine.service.impl;

import com.greensam.pixelengine.pojo.base.PaginationResponse;
import com.greensam.pixelengine.pojo.emuns.StatusEnum;
import com.greensam.pixelengine.pojo.entity.*;
import com.greensam.pixelengine.pojo.vo.user.request.UserPageRequest;
import com.greensam.pixelengine.repository.UserRepository;
import com.greensam.pixelengine.repository.UserRoleRepository;
import com.greensam.pixelengine.service.UserDataService;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author Macro_Ray
 * @since 2025/6/16 18:10
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserDataServiceImpl implements UserDataService {

    private final JPAQueryFactory jpaQueryFactory;
    private final UserRepository userRepository;
    private final UserRoleRepository userRoleRepository;

    @Override
    public Optional<UserPo> getUserByAccount(String account) {
        return userRepository.findByAccountAndDelete(account, Boolean.FALSE);
    }

    @Override
    public List<RolePo> listRoleByUserId(Long userId) {
        QRolePo r = QRolePo.rolePo;
        QUserRolePo ur = QUserRolePo.userRolePo;

        BooleanBuilder condition = new BooleanBuilder();
        condition.and(r.delete.eq(Boolean.FALSE))
                .and(ur.delete.eq(Boolean.FALSE));
        condition.and(ur.userId.eq(userId));

        return jpaQueryFactory.selectFrom(r)
                .leftJoin(ur).on(ur.roleId.eq(r.id))
                .where(condition)
                .fetch();
    }

    @Override
    public UserPo save(UserPo userPo) {
        return userRepository.save(userPo);
    }

    @Override
    public void saveUserRole(UserRolePo userRolePo) {
        userRoleRepository.save(userRolePo);
    }

    @Override
    public PaginationResponse<UserPo> pageUser(UserPageRequest request) {
        QUserPo u = QUserPo.userPo;

        BooleanBuilder condition = new BooleanBuilder();
        condition.and(u.delete.eq(Boolean.FALSE));
        if (StringUtils.isNotBlank(request.getName())) {
            condition.and(u.name.eq(request.getName()));
        }
        if (Objects.nonNull(request.getStatus())) {
            condition.and(u.status.eq(request.getStatus()));
        }
        if (StringUtils.isNotBlank(request.getKeyword())) {
            condition.and(u.name.like("%" + request.getKeyword() + "%"))
                    .or(u.account.like("%" + request.getKeyword() + "%"));
        }

        Long totalCount = jpaQueryFactory.select(u.id.countDistinct())
                .from(u)
                .where(condition)
                .fetchOne();
        if (Objects.isNull(totalCount) || totalCount == 0) {
            return PaginationResponse.empty(request.getPageSize(), request.getPageNum());
        }
        List<UserPo> result = jpaQueryFactory.selectFrom(u)
                .where(condition)
                .offset(request.offset())
                .limit(request.getPageSize())
                .fetch();

        return PaginationResponse.page(result, totalCount, request.getPageSize(), request.getPageNum());
    }

    @Override
    public List<UserPo> getUsersByRoleId(Long id) {
        QUserPo u = QUserPo.userPo;
        QUserRolePo ur = QUserRolePo.userRolePo;

        BooleanBuilder condition = new BooleanBuilder();
        condition.and(u.delete.eq(Boolean.FALSE))
                .and(ur.delete.eq(Boolean.FALSE));
        condition.and(u.status.eq(StatusEnum.Approved));
        condition.and(ur.roleId.eq(id));

        return jpaQueryFactory.selectFrom(u)
                .innerJoin(ur).on(ur.userId.eq(u.id))
                .where(condition)
                .fetch();
    }

    @Override
    public Optional<UserPo> getUserById(Long userId) {
        return userRepository.findByIdAndDelete(userId, Boolean.FALSE);
    }
}
